package cc.cc4414.cc02.system.controller;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.constraints.Pattern;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.google.code.kaptcha.impl.DefaultKaptcha;

import cc.cc4414.cc02.core.aspect.LogAspect;
import cc.cc4414.cc02.core.constant.RegexpConsts;
import cc.cc4414.cc02.core.constant.SessionConsts;
import cc.cc4414.cc02.core.controller.BaseController;
import cc.cc4414.cc02.core.result.ResultEnum;
import cc.cc4414.cc02.core.result.ResultException;
import cc.cc4414.cc02.core.result.ResultVO;
import cc.cc4414.cc02.core.util.IpUtils;
import cc.cc4414.cc02.system.VO.UserVO;
import cc.cc4414.cc02.system.constant.SystemConsts;
import cc.cc4414.cc02.system.converter.User2UserVOConverter;
import cc.cc4414.cc02.system.converter.UserForm2UserConverter;
import cc.cc4414.cc02.system.entity.Role;
import cc.cc4414.cc02.system.entity.User;
import cc.cc4414.cc02.system.form.UserForm;
import cc.cc4414.cc02.system.form.UserRoleForm;
import cc.cc4414.cc02.system.service.UserService;

/**
 * @author cc 2018年6月12日
 */
@Validated
@RestController
@RequestMapping("/user")
public class UserController extends BaseController {

	@Autowired
	private UserService userService;

	@Autowired
	private DefaultKaptcha defaultKaptcha;

	/**
	 * 获取当前登录用户信息
	 * 
	 * @return 用户信息
	 */
	@PostMapping("/me")
	public ResultVO<User> me() {
		User user = getUser();
		// 将密码设为空
		user.setPassword(null);
		return new ResultVO<User>(user);
	}

	/**
	 * 用户注册
	 * 
	 * @param userForm
	 *            用户信息
	 * @param request
	 *            获取ip
	 * @return 是否注册成功
	 */
	@PostMapping("reg")
	public ResultVO<Object> reg(@Validated({ UserForm.Reg.class }) @RequestBody UserForm userForm,
			HttpServletRequest request) {
		User user = UserForm2UserConverter.convert(userForm);
		String ip = IpUtils.getIp(request);
		user.setIp(ip);
		userService.save(user);
		return new ResultVO<>(ResultEnum.SUCCESS);
	}

	/**
	 * 新增用户
	 * 
	 * @param userForm
	 *            用户信息
	 * @param request
	 *            获取ip
	 * @return 是否新增成功
	 */
	@PostMapping("add")
	public ResultVO<Object> add(@Validated({ UserForm.Add.class }) @RequestBody UserForm userForm,
			HttpServletRequest request) {
		User user = UserForm2UserConverter.convert(userForm);
		String ip = IpUtils.getIp(request);
		user.setIp(ip);
		user.setPassword(SystemConsts.DEFAULT_PASSWORD);
		userService.save(user);
		return new ResultVO<>(ResultEnum.SUCCESS);
	}

	/**
	 * 检查用户是否存在
	 * 
	 * @param username
	 *            用户名
	 * @return 用户存在为true，用户不存在为false
	 */
	@GetMapping("checkUser")
	public ResultVO<Boolean> checkUser(@Pattern(regexp = RegexpConsts.USERNAME) @RequestParam String username) {
		ResultVO<Boolean> resultVO = new ResultVO<Boolean>(ResultEnum.SUCCESS);
		User user = userService.findByUsername(username);
		if (user != null) {
			resultVO.setData(true);
		} else {
			resultVO.setData(false);
		}
		return resultVO;
	}

	/**
	 * 通过用户名查找用户
	 * 
	 * @param username
	 *            用户名
	 * @return 查找到的用户
	 */
	@GetMapping("findUser")
	public ResultVO<UserVO> findUser(@RequestParam String username) {
		ResultVO<UserVO> resultVO = new ResultVO<UserVO>(ResultEnum.SUCCESS);
		User user = userService.findByUsername(username);
		if (user != null && user.getState().equals(0)) {
			resultVO.setData(User2UserVOConverter.convert(user));
		}
		return resultVO;
	}

	/**
	 * 退出登录
	 * 
	 * @return 是否退出登录成功
	 */
	@PostMapping("logout")
	public ResultVO<Object> logout(Authentication authentication) {
		removeToken(authentication);
		return new ResultVO<>(ResultEnum.SUCCESS);
	}

	/**
	 * 修改密码
	 * 
	 * @param password
	 *            修改后的新密码
	 * @param oldPassword
	 *            原密码
	 * @return 是否修改成功
	 */
	@PostMapping("changePassword")
	public ResultVO<Object> changePassword(@Pattern(regexp = RegexpConsts.PASSWORD) @RequestParam String password,
			@Pattern(regexp = RegexpConsts.PASSWORD) @RequestParam String oldPassword) {
		User user = getUser();
		// 校验原密码
		String encodedPassword = userService.findByUsername(user.getUsername()).getPassword();
		PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
		if (!passwordEncoder.matches(oldPassword, encodedPassword)) {
			throw new ResultException(ResultEnum.PASSWORD_ERROR);
		}
		// 修改为新密码
		userService.updatePassword(user.getId(), password);
		return new ResultVO<>(ResultEnum.SUCCESS);
	}

	/**
	 * 管理员分页查询用户的信息
	 * 
	 * @param page
	 *            当前页数，从0开始计算
	 * @param size
	 *            每页行数
	 * @return 分页查询用户的信息
	 */
	@GetMapping("findAll")
	public ResultVO<Page<User>> findAll(@RequestParam int page, @RequestParam int size) {
		Page<User> pageUser = userService.findAll(page, size);
		pageUser.getContent().stream().forEach(e -> e.setPassword(null));
		return new ResultVO<Page<User>>(pageUser);
	}

	/**
	 * 通过用户id删除用户(将state设置为1)
	 * 
	 * @param id
	 *            用户id
	 * @return 是否删除成功
	 */
	@PostMapping("delete")
	@LogAspect("删除用户")
	public ResultVO<Object> delete(@RequestParam Long id) {
		userService.delete(id);
		return new ResultVO<>(ResultEnum.SUCCESS);
	}

	/**
	 * 重置密码
	 * 
	 * @param id
	 *            用户id
	 * @return 是否重置成功
	 */
	@PostMapping("resetPassword")
	@LogAspect("重置用户密码")
	public ResultVO<Object> resetPassword(@RequestParam Long id) {
		userService.resetPassword(id);
		return new ResultVO<>(ResultEnum.SUCCESS);
	}

	/**
	 * 修改用户信息
	 * 
	 * @param userForm
	 *            修改后的用户
	 * @return 是否修改成功
	 */
	@PostMapping("update")
	@LogAspect("修改用户信息")
	public ResultVO<Object> update(@Validated({ UserForm.Update.class }) @RequestBody UserForm userForm) {
		User user = UserForm2UserConverter.convert(userForm);
		userService.update(user);
		return new ResultVO<>(ResultEnum.SUCCESS);
	}

	/**
	 * 通过用户id查找该用户拥有的角色
	 * 
	 * @param userId
	 *            用户id
	 * @return 该用户拥有的角色
	 */
	@GetMapping("findRole")
	public ResultVO<List<Role>> findRole(@RequestParam Long userId) {
		return new ResultVO<List<Role>>(userService.findRoleByUserId(userId));
	}

	/**
	 * 修改用户所拥有的所有角色
	 * 
	 * @param userRole
	 *            用户id和用户所拥有的角色id
	 * @return 是否修改成功
	 */
	@PostMapping("updateUserRole")
	@LogAspect("修改用户角色")
	public ResultVO<Object> updateUserRole(@Validated @RequestBody UserRoleForm userRole) {
		userService.updateUserRole(userRole.getUserId(), userRole.getRoleIds());
		return new ResultVO<>(ResultEnum.SUCCESS);
	}

	/**
	 * 生成验证码并保存至session
	 * 
	 * @param session
	 * @param response
	 */
	@GetMapping("captcha")
	public void captcha(HttpSession session, HttpServletResponse response) {
		response.setContentType("image/jpeg");
		String text = defaultKaptcha.createText();
		session.setAttribute(SessionConsts.CAPTCHA, text);
		BufferedImage image = defaultKaptcha.createImage(text);
		try {
			ImageIO.write(image, "jpg", response.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
